
package com.neusoft.bizcore.activiti.service.impl;

import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.activiti.bpmn.model.BpmnModel;
import org.activiti.bpmn.model.EndEvent;
import org.activiti.bpmn.model.ExclusiveGateway;
import org.activiti.bpmn.model.FlowElement;
import org.activiti.bpmn.model.FlowNode;
import org.activiti.bpmn.model.SequenceFlow;
import org.activiti.bpmn.model.StartEvent;
import org.activiti.bpmn.model.UserTask;
import org.activiti.editor.language.json.converter.util.CollectionUtils;
import org.activiti.engine.HistoryService;
import org.activiti.engine.IdentityService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.history.HistoricTaskInstanceQuery;
import org.activiti.engine.impl.bpmn.behavior.ParallelMultiInstanceBehavior;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.Execution;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.activiti.engine.task.TaskQuery;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.neusoft.bizcore.activiti.constants.BizcoreActivitiConstants;
import com.neusoft.bizcore.activiti.diagram.CustomProcessDiagramGenerator;
import com.neusoft.bizcore.activiti.dto.ProcessInstanceDTO;
import com.neusoft.bizcore.activiti.dto.RecordDTO;
import com.neusoft.bizcore.activiti.dto.TaskDTO;
import com.neusoft.bizcore.activiti.dto.WorkorderDTO;
import com.neusoft.bizcore.activiti.enums.ProcessNodeType;
import com.neusoft.bizcore.activiti.enums.WorkOrderStatus;
import com.neusoft.bizcore.activiti.service.ProcessFormService;
import com.neusoft.bizcore.activiti.service.ProcessInstanceService;
import com.neusoft.bizcore.activiti.service.WorkOrderService;
import com.neusoft.bizcore.activiti.user.ActivitiUserDetail;
import com.neusoft.bizcore.auth.common.bean.UserBean;
import com.neusoft.bizcore.web.exception.UnitedException;

@Service
public class ProcessInstanceServiceImpl implements ProcessInstanceService {

    @Autowired
    private IdentityService identityService;
    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private TaskService taskService;
    @Autowired
    private WorkOrderService workorderService;
    @Autowired
    private HistoryService historyService;
    @Autowired
    private RepositoryService repositoryService;
    @Autowired
    private ActivitiUserDetail userDetail;
    @Autowired
    private ProcessFormService processFormService;

    @Override
    public ProcessInstanceDTO start(final String type, final String businessKey, final UserBean user) {

        ProcessInstance pi;

        if (StringUtils.isEmpty(type)) {
            throw new UnitedException(BizcoreActivitiConstants.PROCESS_EXIST);
        }

        if (null == user) {
            throw new UnitedException(BizcoreActivitiConstants.PROCESS_USER_EXIST);
        }

        // 启动人信息
        final Map<String, Object> variables = new HashMap<>();

        // 设置启动人
        this.identityService.setAuthenticatedUserId(user.getUsername());
        variables.put(BizcoreActivitiConstants.START_USER_INFO_KEY, user);
        // 设置流程类型
        variables.put(BizcoreActivitiConstants.START_TYPE_KEY, type);
        // 启动人
        variables.put(BizcoreActivitiConstants.START_USER_CODE_KEY, user.getUsername());
        // 启动流程实例
        pi = this.runtimeService.createProcessInstanceBuilder().processDefinitionKey(type)
                .businessKey(businessKey).variables(variables).start();

        final Task task = this.taskService.createTaskQuery().processInstanceId(pi.getProcessInstanceId())
                .singleResult();

        this.taskService.setAssignee(task.getId(), user.getUsername());

        return new ProcessInstanceDTO(pi.getProcessInstanceId(), pi.getBusinessKey(), task.getId());
    }

    @Override
    public void complete(final String workorderNum, final String taskId, final UserBean user) {

        if (null == workorderNum) {
            throw new UnitedException(BizcoreActivitiConstants.WORK_ORDER_EXIST);
        }

        final String instanceId = this.workorderService.getInstanceIdByWorkorderNum(workorderNum);

        if (instanceId == null) {
            throw new UnitedException(BizcoreActivitiConstants.PROCESS_EXIST);
        }
        if (taskId == null) {
            throw new UnitedException(BizcoreActivitiConstants.TASK_NOT_EXIST);
        }
        final Task task = this.taskService.createTaskQuery().taskId(taskId).singleResult();
        if (task == null) {
            throw new UnitedException(BizcoreActivitiConstants.TASK_NOT_EXIST);
        }

        //任务拾取
        if ((user != null) && StringUtils.isEmpty(task.getAssignee())) {
            this.taskService.claim(task.getId(), user.getUsername());
        }

        // 完成当前节点
        try {
            //多实例任务处理
            this.handleMultiInstance(workorderNum, instanceId, taskId);
            // 完成任务
            this.taskService.complete(task.getId());

            // 判断当前实例是否存在，不存在的情况下修改工单状态
            final List<Task> checkList = this.taskService.createTaskQuery().processInstanceId(instanceId).list();
            if (CollectionUtils.isEmpty(checkList)) {
                this.workorderService.updateStatus(workorderNum, WorkOrderStatus.finish);
            }

            // 更新时间
            this.workorderService.updateTime(workorderNum);

        } catch (final Exception e) {
            throw new UnitedException(BizcoreActivitiConstants.PROCESS_CONDITIONS_NOT);
        }
    }

    @Override
    public void finishOfNotPass(final String workorderNum, final String taskId, final UserBean user) {

        final String instanceId = this.workorderService.getInstanceIdByWorkorderNum(workorderNum);
        if (instanceId == null) {
            throw new UnitedException(BizcoreActivitiConstants.PROCESS_EXIST);
        }

        final List<Task> task = this.taskService.createTaskQuery().processInstanceId(instanceId).list();
        task.forEach(ele -> this.taskService.claim(ele.getId(), user.getUsername()));
        this.runtimeService.deleteProcessInstance(instanceId, BizcoreActivitiConstants.PROCESS_NOT_PASS_REASON);

    }

    @Override
    public void setGlobalVariable(final String taskId, final String variableName, final Object value) {

        final Map<String, Object> variables = new HashMap<>();
        if (null != variableName) {
            variables.put(variableName, value);
        }

        this.setProcessVariables(taskId, variables);

    }

    @Override
    public void setGlobalVariables(final String taskId, final Map<String, Object> variables) {
        this.setProcessVariables(taskId, variables);
    }

    @Override
    public Map<String, Object> getVariables(final String workorderNum, final List<String> variableNames,
            final String type) {

        final String instanceId = this.workorderService.getInstanceIdByWorkorderNum(workorderNum);
        if (instanceId == null) {
            throw new UnitedException(BizcoreActivitiConstants.PROCESS_EXIST);
        }

        final List<Execution> executions =
                this.runtimeService.createExecutionQuery().processInstanceId(instanceId).list();

        if (CollectionUtils.isEmpty(executions)) {
            throw new UnitedException(BizcoreActivitiConstants.PROCESS_EXIST);
        }

        final Execution execution = executions.get(0);

        //TODO 以后二期进行转换
        final List<String> transformVariableNames = variableNames;
        // 从流程变量里面取值
        final Map<String, Object> result = this.runtimeService.getVariables(execution.getId(), transformVariableNames);

        return result;

    }

    @Override
    public Object getVariables(final String workorderNum, final String variableName, final String type) {

        Object result = null;

        final String instanceId = this.workorderService.getInstanceIdByWorkorderNum(workorderNum);

        if (instanceId != null) {
            final List<Execution> executions =
                    this.runtimeService.createExecutionQuery().processInstanceId(instanceId).list();
            if ((executions != null) && (executions.size() > 0)) {
                final Execution execution = executions.get(0);
                //TODO 以后二期进行转换
                result = this.runtimeService.getVariable(execution.getId(), variableName);
            }
        }

        return result;
    }

    private void setProcessVariables(final String taskId, final Map<String, Object> variables) {

        if (null == taskId) {
            throw new UnitedException(BizcoreActivitiConstants.TASK_NOT_EXIST);
        }

        this.taskService.setVariables(taskId, variables);
    }

    @Override
    public String getNodeIdByTaskId(final String taskId) {

        final HistoricTaskInstance hisTask =
                this.historyService.createHistoricTaskInstanceQuery().taskId(taskId).singleResult();

        if (hisTask == null) {
            throw new UnitedException(BizcoreActivitiConstants.TASK_NOT_EXIST);
        }

        //获得流程定义
        final String processDefinitionId = hisTask.getProcessDefinitionId();

        // 取得已提交的任务
        final HistoricTaskInstance historicTaskInstance =
                this.historyService.createHistoricTaskInstanceQuery().taskId(taskId).singleResult();

        final List<Execution> executionList =
                this.runtimeService.createExecutionQuery().executionId(historicTaskInstance.getExecutionId()).list();

        final String activityId = executionList.get(0).getActivityId();

        final FlowElement node =
                this.repositoryService.getBpmnModel(processDefinitionId).getMainProcess().getFlowElement(activityId);

        return node.getId();
    }

    /**
     * description: 设置流程的审批人
     *
     * @param taskId 任务ID
     * @param user 当前用户
     */
    @Override
    public void claim(final String taskId, final UserBean user) {

        if (taskId == null) {
            throw new UnitedException(BizcoreActivitiConstants.TASK_NOT_EXIST);
        }

        if (user == null) {
            throw new UnitedException(BizcoreActivitiConstants.PROCESS_USER_EXIST);
        }

        this.taskService.claim(taskId, user.getUsername());
    }

    /**
     * description: 获取待办任务
     *
     * @param user 当前用户
     * @return List<TaskDTO>
     */
    @Override
    public List<TaskDTO> getTodoTask(final UserBean user) {

        // 创建任务查询
        final TaskQuery taskQuery = this.taskService.createTaskQuery();

        // 人员查询
        if (null != user) {

            final String userName = user.getUsername();

            if (StringUtils.isNotEmpty(userName)) {
                taskQuery.or();
                taskQuery.taskCandidateOrAssigned(userName);
                // 角色
                final List<String> roles = user.getRoles().stream().map(s -> s.getRole()).collect(Collectors.toList());
                if (roles != null) {
                    taskQuery.taskCandidateGroupIn(roles);
                }
                taskQuery.endOr();
            }
        }

        final List<Task> taskList = taskQuery.list();

        return taskList.stream().map(k -> {
            return TaskDTO.builder().instanceId(k.getProcessInstanceId()).taskId(k.getId()).build();
        }).distinct().collect(Collectors.toList());
    }

    /**
     * description: 获取已办任务
     *
     * @param user 当前用户
     * @return List<TaskDTO>
     */
    @Override
    public List<TaskDTO> getDoneTask(final UserBean user) {

        final HistoricTaskInstanceQuery query = this.historyService.createHistoricTaskInstanceQuery();

        final List<String> currentTaskIds = this.taskService.createTaskQuery().list().stream().map(k -> k.getId())
                .distinct().collect(Collectors.toList());
        // 人员查询
        if (null != user) {

            final String userName = user.getUsername();

            if (StringUtils.isNotEmpty(userName)) {
                query.taskAssignee(userName);
            }
        }

        final List<HistoricTaskInstance> taskList = query.list();

        return taskList.stream().filter(s -> !currentTaskIds.contains(s.getId())).map(k -> {
            return TaskDTO.builder().instanceId(k.getProcessInstanceId()).taskId(k.getId()).build();
        }).collect(Collectors.toList());
    }

    /**
     * description: 获取流程履历
     *
     * @param workorderNum 工单号
     * @param user 当前用户
     * @return List<RecordDTO>
     */
    @Override
    public List<RecordDTO> getRecords(final String workorderNum, final UserBean user) {

        final List<RecordDTO> result = new ArrayList<>();

        if (null == user) {
            throw new UnitedException(BizcoreActivitiConstants.PROCESS_USER_EXIST);
        }

        if (null == workorderNum) {
            throw new UnitedException(BizcoreActivitiConstants.WORK_ORDER_EXIST);
        }

        final WorkorderDTO workForm = this.workorderService.details(workorderNum);

        final String instanceId = workForm.getInstanceId();

        // 流程实例ID
        if (StringUtils.isEmpty(instanceId)) {
            throw new UnitedException(BizcoreActivitiConstants.PROCESS_EXIST);
        }

        // 查询当前的任务ID
        final List<String> currentTaskIds = new ArrayList<>();
        final List<Task> tasks = this.taskService.createTaskQuery().processInstanceId(instanceId).list();

        // 判断当前任务是否是当期登录用户
        final List<String> roles = user.getRoles().stream().map(s -> s.getRole()).collect(Collectors.toList());
        final List<Task> checkTask = this.taskService.createTaskQuery().processInstanceId(instanceId).or()
                .taskCandidateOrAssigned(user.getUsername()).taskCandidateGroupIn(roles)
                .endOr().list();
        // 判断登录人是否有操作权限
        final Boolean containPermissions =
                CollectionUtils.isNotEmpty(checkTask) || user.getUsername().equals(workForm.getApplyUserId());

        // 获取当前任务的所有任务ID
        if (CollectionUtils.isNotEmpty(tasks)) {
            tasks.stream().map(s -> {
                return s.getId();
            }).forEach(currentTaskIds::add);
        }

        // 该流程实例的所有节点审批记录
        List<HistoricActivityInstance> hisActInstList =
                this.historyService.createHistoricActivityInstanceQuery().processInstanceId(instanceId)
                        .activityType(ProcessNodeType.userTask.toString()).orderByHistoricActivityInstanceStartTime()
                        .desc().list();

        // 没有权限的筛选出能看到的数据
        if (!containPermissions) {
            final List<HistoricActivityInstance> removeList = new ArrayList<>();
            // 查询到最后一次登录人数据的定位
            for (final HistoricActivityInstance element : hisActInstList) {
                // 任务处理人
                if (user.getUsername().equals(element.getAssignee())) {
                    break;
                } else {
                    removeList.add(element);
                }
            }

            hisActInstList.removeAll(removeList);
        } else {

            // 去掉别人的任务
            if (CollectionUtils.isNotEmpty(tasks) && CollectionUtils.isNotEmpty(checkTask)) {

                final List<String> currentUserTaskIds =
                        checkTask.stream().map(s -> s.getId()).collect(Collectors.toList());

                final List<String> otherUserTaskIds = currentTaskIds.stream()
                        .filter(s -> !currentUserTaskIds.contains(s)).collect(Collectors.toList());
                if (CollectionUtils.isNotEmpty(otherUserTaskIds)) {

                    hisActInstList = hisActInstList.stream().filter(s -> !otherUserTaskIds.contains(s.getTaskId()))
                            .collect(Collectors.toList());
                }
            }
        }

        // 在正序
        Collections.reverse(hisActInstList);

        hisActInstList.stream().map(k -> {

            final HistoricTaskInstance hisTask =
                    this.historyService.createHistoricTaskInstanceQuery().taskId(k.getTaskId()).singleResult();

            UserBean assignee = null;
            if (StringUtils.isNotEmpty(k.getAssignee())) {
                assignee = this.userDetail.getUserInfo(k.getAssignee());
            }

            return RecordDTO.builder()
                    .formKey(hisTask.getFormKey())
                    .nodeName(this.processFormService.getFormNameBykey(hisTask.getFormKey()))
                    .isCurrent(currentTaskIds.contains(k.getTaskId()))
                    .taskId(k.getTaskId())
                    .workOrderNum(workorderNum)
                    .isShow(true)
                    .applyTime(k.getEndTime() != null ? new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(k.getEndTime()) : "")
                    .approveUser(assignee == null ? "" : assignee.getName())
                    .active(currentTaskIds.contains(k.getTaskId()))
                    .build();
        }).forEach(result::add);

        if (user.getUsername().equals(workForm.getApplyUserId()) && CollectionUtils.isEmpty(checkTask)
                && CollectionUtils.isNotEmpty(tasks) && CollectionUtils.isNotEmpty(result)) {
            result.get(result.size() - 1).setIsShow(false);
        }

        return result;
    }

    @Override
    public List<RecordDTO> getRecords(final String workorderNum) {

        final List<RecordDTO> result = new ArrayList<>();

        if (null == workorderNum) {
            throw new UnitedException(BizcoreActivitiConstants.WORK_ORDER_EXIST);
        }

        final WorkorderDTO workForm = this.workorderService.details(workorderNum);

        final String instanceId = workForm.getInstanceId();

        // 流程实例ID
        if (StringUtils.isEmpty(instanceId)) {
            throw new UnitedException(BizcoreActivitiConstants.PROCESS_EXIST);
        }

        // 查询当前的任务ID
        final List<String> currentTaskIds = new ArrayList<>();
        final List<Task> tasks = this.taskService.createTaskQuery().processInstanceId(instanceId).list();

        // 获取当前任务的所有任务ID
        if (CollectionUtils.isNotEmpty(tasks)) {
            tasks.stream().map(s -> {
                return s.getId();
            }).forEach(currentTaskIds::add);
        }

        // 该流程实例的所有节点审批记录
        final List<HistoricActivityInstance> hisActInstList =
                this.historyService.createHistoricActivityInstanceQuery().processInstanceId(instanceId)
                        .activityType(ProcessNodeType.userTask.toString()).orderByHistoricActivityInstanceStartTime()
                        .desc().list();

        // 在正序
        Collections.reverse(hisActInstList);

        hisActInstList.stream().map(k -> {

            final HistoricTaskInstance hisTask =
                    this.historyService.createHistoricTaskInstanceQuery().taskId(k.getTaskId()).singleResult();

            UserBean assignee = null;
            if (StringUtils.isNotEmpty(k.getAssignee())) {
                assignee = this.userDetail.getUserInfo(k.getAssignee());
            }

            return RecordDTO.builder()
                    .formKey(hisTask.getFormKey())
                    .nodeName(this.processFormService.getFormNameBykey(hisTask.getFormKey()))
                    .isCurrent(currentTaskIds.contains(k.getTaskId()))
                    .taskId(k.getTaskId())
                    .workOrderNum(workorderNum)
                    .isShow(true)
                    .applyTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(k.getStartTime()))
                    .approveUser(assignee == null ? "" : assignee.getName())
                    .active(currentTaskIds.contains(k.getTaskId()))
                    .build();
        }).forEach(result::add);

        return result;
    }

    @Override
    public String getLastTaskId(final String taskId, final UserBean user) {

        String lastTaskId = null;

        final Task task = this.taskService.createTaskQuery().taskId(taskId).singleResult();

        if (task != null) {

            final List<HistoricActivityInstance> historicActivityInstance =
                    this.historyService.createHistoricActivityInstanceQuery()
                            .processInstanceId(task.getProcessInstanceId())
                            .taskAssignee(user.getUsername()).list();

            Collections.reverse(historicActivityInstance);

            final List<HistoricActivityInstance> filterData = historicActivityInstance.stream()
                    .filter(k -> taskId.equals(k.getTaskId())).collect(Collectors.toList());

            // 循环找到上个节点任务
            if (CollectionUtils.isNotEmpty(filterData)) {
                final String nodeId = filterData.get(0).getActivityId();
                final List<HistoricActivityInstance> nodes = historicActivityInstance.stream()
                        .filter(k -> nodeId.equals(k.getActivityId())).collect(Collectors.toList());
                if (CollectionUtils.isNotEmpty(nodes) && (nodes.size() >= 2) && this.isRejected(task)) {
                    lastTaskId = nodes.get(1).getTaskId();
                }
            }
        }

        return lastTaskId;
    }

    /**
     * description: 判断是否为驳回节点
     *
     * @param taskId 任务ID
     * @return
     */
    private Boolean isRejected(final Task task) {
        final Boolean isRejected = false;
        final Task task2 = task;
        if (task2 == null) {
            return isRejected;
        }

        final List<HistoricActivityInstance> historicInstance =
                this.historyService.createHistoricActivityInstanceQuery()
                        .processInstanceId(task2.getProcessInstanceId()).list();

        Collections.reverse(historicInstance);

        // 当前节点ID
        final String currentNodeId = task2.getTaskDefinitionKey();
        // 上个节点ID
        String upNodeId = null;
        for (int i = 0; i < historicInstance.size(); i++) {
            if (historicInstance.get(i).getTaskId().equals(task2.getId()) && ((i + 1) < historicInstance.size())) {
                upNodeId = historicInstance.get(i + 1).getActivityId();
                break;
            }
        }

        if ((currentNodeId != null) && (upNodeId != null)) {
            final Map<String, Integer> map = new HashMap<>();
            //获取BPMN模型节点
            final BpmnModel bpmnModel =
                    this.repositoryService.getBpmnModel(task2.getProcessDefinitionId());

            final Collection<FlowElement> flowElements = bpmnModel.getMainProcess().getFlowElements();

            if (CollectionUtils.isNotEmpty(flowElements)) {
                final StartEvent element =
                        flowElements.stream().filter(k -> k instanceof StartEvent).map(m -> (StartEvent) m)
                                .collect(Collectors.toList()).get(0);
                map.put(element.getId(), 0);

                final List<SequenceFlow> outs = element.getOutgoingFlows();

                this.sortElements(outs, element.getId(), map);
            }

            return map.get(currentNodeId) < map.get(upNodeId);
        }

        return isRejected;
    }

    private void sortElements(final List<SequenceFlow> outs, final String nodeId, final Map<String, Integer> map) {

        if (outs != null) {

            for (final SequenceFlow out : outs) {
                final FlowElement target = out.getTargetFlowElement();
                if ((target != null) && !map.containsKey(target.getId())) {
                    map.put(target.getId(), map.get(nodeId) + 1);
                    if (target instanceof UserTask) {
                        this.sortElements(((UserTask) target).getOutgoingFlows(), target.getId(), map);
                    } else if (target instanceof StartEvent) {
                        this.sortElements(((StartEvent) target).getOutgoingFlows(), target.getId(), map);
                    } else if (target instanceof ExclusiveGateway) {
                        this.sortElements(((ExclusiveGateway) target).getOutgoingFlows(), target.getId(), map);
                    }
                }
            }
        }
    }

    /**
     * description: 多实例处理
     *
     * @param instanceId
     * @param task
     */
    private void handleMultiInstance(final String workorderNum, final String instanceId, final String taskId) {

        final List<Task> tasks = this.taskService.createTaskQuery().processInstanceId(instanceId).list();

        final Task task = this.taskService.createTaskQuery().taskId(taskId).singleResult();

        final List<String> variableNames = new ArrayList<>();
        variableNames.add("passFlag");

        final Map<String, Object> condition =
                this.getVariables(workorderNum, variableNames, BizcoreActivitiConstants.VARIABLE_TYPE_FORM);

        //判断是否是多实例任务
        final BpmnModel bpmnModel =
                this.repositoryService.getBpmnModel(task.getProcessDefinitionId());
        boolean flag = false;
        final FlowElement flowElement = bpmnModel.getFlowElement(task.getTaskDefinitionKey());
        // 根据活动id获取活动实例
        if (flowElement instanceof UserTask) {
            final UserTask userTask = (UserTask) flowElement;
            if (userTask.getBehavior() instanceof ParallelMultiInstanceBehavior) {
                final ParallelMultiInstanceBehavior behavior = (ParallelMultiInstanceBehavior) userTask.getBehavior();
                if (behavior != null) {
                    flag = true;
                }
            }
        }

        if (flag && (condition.get("passFlag") != null)) {
            final Boolean passFlag = (Boolean) condition.get("passFlag");
            int passCount = 0;//审批同意人数
            int totalCount = 0;//任务总人数
            int refuseCount = 0; //拒绝人数
            //当前的执行情况
            final String tmpPassCount =
                    this.runtimeService.getVariable(instanceId, task.getTaskDefinitionKey() + "#pass") + "";
            final String tmpRefuseCount =
                    this.runtimeService.getVariable(instanceId, task.getTaskDefinitionKey() + "#refuse") + "";
            final String tmpTotal =
                    this.runtimeService.getVariable(instanceId, task.getTaskDefinitionKey() + "#total") + "";
            if (StringUtils.isNotBlank(tmpPassCount) && !tmpPassCount.equals("null")) {
                passCount = Integer.parseInt(tmpPassCount);
            }
            if (StringUtils.isNotBlank(tmpRefuseCount) && !tmpPassCount.equals("null")) {
                refuseCount = Integer.parseInt(tmpRefuseCount);
            }

            if (StringUtils.isNotBlank(tmpTotal) && !tmpTotal.equals("null")) {
                totalCount = Integer.parseInt(tmpTotal);
            } else {
                totalCount = tasks.size();
            }
            for (final Task tmp : tasks) {
                if (tmp.getId().equals(task.getId())) {
                    if (passFlag) {
                        passCount++;
                    } else {
                        refuseCount++;
                    }
                }
            }

            //变量回写记录
            final Map<String, Object> variables = new HashMap<>();
            variables.put("pass", passCount);
            variables.put("total", totalCount);
            variables.put("refuse", refuseCount);
            variables.put(task.getTaskDefinitionKey() + "#pass", passCount);
            variables.put(task.getTaskDefinitionKey() + "#total", totalCount);
            variables.put(task.getTaskDefinitionKey() + "#refuse", refuseCount);
            this.setGlobalVariables(taskId, variables);
        }
    }

    @Override
    public InputStream getImage(final String type, final String workOrderNum, final boolean showHistory) {
        InputStream imageStream = null;
        BpmnModel bpmnModel = null;
        String procInstId = null;
        String workType = type;
        Boolean isRevoke = false;
        if (StringUtils.isNotEmpty(workOrderNum)) {
            final WorkorderDTO model = this.workorderService.details(workOrderNum);
            if (model != null) {
                procInstId = model.getInstanceId();
                workType = model.getType();
                isRevoke = model.getStatus().equals(WorkOrderStatus.revoked);
            }
        }

        final List<String> highLightedActivitiIdList = new ArrayList<>();
        final List<String> runningActivitiIdList = new ArrayList<>();
        final List<String> highLightedFlowIds = new ArrayList<>();
        final List<String> revokeFlowIds = new ArrayList<>();

        if (showHistory && StringUtils.isNotEmpty(procInstId)) {
            // 通过流程实例ID获取历史流程实例
            final HistoricProcessInstance historicProcessInstance = this.historyService
                    .createHistoricProcessInstanceQuery()
                    .processInstanceId(procInstId)
                    .singleResult();

            if (null != historicProcessInstance) {

                // 获取流程定义Model对象
                bpmnModel = this.repositoryService.getBpmnModel(historicProcessInstance.getProcessDefinitionId());

                //如果需要展示历史节点记录，则需要查询出对应的历史节点信息
                if (showHistory) {
                    // 通过流程实例ID获取流程中已经执行的节点，按照执行先后顺序排序
                    final List<HistoricActivityInstance> historicActivityInstanceList =
                            this.historyService.createHistoricActivityInstanceQuery()
                                    .processInstanceId(procInstId)
                                    .orderByHistoricActivityInstanceId()
                                    .asc().list();

                    // 将已经执行的节点ID放入高亮显示节点集合
                    for (final HistoricActivityInstance historicActivityInstance : historicActivityInstanceList) {
                        highLightedActivitiIdList.add(historicActivityInstance.getActivityId());
                    }

                    // 通过流程实例ID获取流程中正在执行的节点
                    final List<Execution> runningActivityInstanceList =
                            this.runtimeService.createExecutionQuery().processInstanceId(procInstId).list();
                    for (final Execution execution : runningActivityInstanceList) {
                        if (StringUtils.isNotEmpty(execution.getActivityId())) {
                            runningActivitiIdList.add(execution.getActivityId());
                        }
                    }

                    // 获取已流经的流程线，需要高亮显示高亮流程已发生流转的线id集合
                    highLightedFlowIds.addAll(this.getHighLightedFlows(bpmnModel, historicActivityInstanceList));

                    // 如果是撤销节点显示撤销
                    if (isRevoke) {
                        revokeFlowIds.add(historicActivityInstanceList.get(historicActivityInstanceList.size() - 1)
                                .getActivityId());
                        // 放入到已经走完的节点中
                        final Collection<FlowElement> flowElements = bpmnModel.getMainProcess().getFlowElements();
                        if (CollectionUtils.isNotEmpty(flowElements)) {
                            final List<EndEvent> elements =
                                    flowElements.stream().filter(k -> k instanceof EndEvent).map(m -> (EndEvent) m)
                                            .collect(Collectors.toList());
                            elements.stream().map(l -> l.getId()).forEach(highLightedActivitiIdList::add);
                        }
                    }
                }
            }
        }
        // 默认走第一个节点
        else if (showHistory && StringUtils.isNotEmpty(workType) && StringUtils.isEmpty(procInstId)) {

            final List<Deployment> deploymentList =
                    this.repositoryService.createDeploymentQuery().processDefinitionKey(workType).list();

            if (CollectionUtils.isNotEmpty(deploymentList)) {
                final ProcessDefinition processDefinition = this.repositoryService.createProcessDefinitionQuery()
                        .deploymentId(deploymentList.get(deploymentList.size() - 1).getId()).singleResult();

                if (processDefinition != null) {
                    // 将开始节点和第一个节点放入执行节点中

                    bpmnModel =
                            this.repositoryService.getBpmnModel(processDefinition.getId());

                    if (bpmnModel != null) {
                        final Collection<FlowElement> flowElements = bpmnModel.getMainProcess().getFlowElements();

                        if (CollectionUtils.isNotEmpty(flowElements)) {
                            final StartEvent element =
                                    flowElements.stream().filter(k -> k instanceof StartEvent).map(m -> (StartEvent) m)
                                            .collect(Collectors.toList()).get(0);

                            if (element != null) {
                                // 已经执行的节点 开始节点 第一个表单
                                highLightedActivitiIdList.add(element.getId());
                                element.getOutgoingFlows().stream().map(s -> s.getTargetFlowElement().getId())
                                        .forEach(highLightedActivitiIdList::add);

                                // 已正在执行的节点
                                element.getOutgoingFlows().stream().map(s -> s.getTargetFlowElement().getId())
                                        .forEach(runningActivitiIdList::add);

                                // 已经执行的线
                                highLightedFlowIds.add(element.getOutgoingFlows().get(0).getId());
                            }

                        }
                    }
                } else {
                    throw new UnitedException(BizcoreActivitiConstants.PROCESS_EXIST);
                }
            }

        }
        // 查看原始的流程图
        else if (!showHistory && StringUtils.isNotEmpty(workType)) {
            final List<Deployment> deploymentList =
                    this.repositoryService.createDeploymentQuery().processDefinitionKey(workType).list();

            if (CollectionUtils.isNotEmpty(deploymentList)) {
                final ProcessDefinition processDefinition = this.repositoryService.createProcessDefinitionQuery()
                        .deploymentId(deploymentList.get(deploymentList.size() - 1).getId()).singleResult();
                if (processDefinition != null) {
                    bpmnModel = this.repositoryService.getBpmnModel(processDefinition.getId());
                } else {
                    throw new UnitedException(BizcoreActivitiConstants.PROCESS_EXIST);
                }
            } else {
                throw new UnitedException(BizcoreActivitiConstants.PROCESS_EXIST);
            }
        } else {
            throw new UnitedException(BizcoreActivitiConstants.PROCESS_EXIST);
        }

        try {
            if (null != bpmnModel) {
                // 定义流程画布生成器
                final CustomProcessDiagramGenerator processDiagramGenerator = new CustomProcessDiagramGenerator();

                // 使用默认配置获得流程图表生成器，并生成追踪图片字符流
                imageStream = processDiagramGenerator.generateDiagramCustom(bpmnModel, "png",
                        highLightedActivitiIdList, runningActivitiIdList, highLightedFlowIds, revokeFlowIds,
                        "宋体", "黑体", "黑体",
                        null, 2.0);
            }

        } catch (final Exception e) {
            throw new UnitedException("通过流程实例ID" + procInstId + "获取流程图时出现异常！", e);
        }

        return imageStream;
    }

    private List<String> getHighLightedFlows(final BpmnModel bpmnModel,
            final List<HistoricActivityInstance> historicActivityInstanceList) {
        // 已流经的流程线，需要高亮显示
        final List<String> highLightedFlowIdList = new ArrayList<>();
        // 全部活动节点
        final List<FlowNode> allHistoricActivityNodeList = new ArrayList<>();
        // 已完成的历史活动节点
        final List<HistoricActivityInstance> finishedActivityInstanceList = new ArrayList<>();

        for (final HistoricActivityInstance historicActivityInstance : historicActivityInstanceList) {
            // 获取流程节点
            final FlowNode flowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(historicActivityInstance
                    .getActivityId(), true);
            allHistoricActivityNodeList.add(flowNode);
            // 结束时间不为空，当前节点则已经完成
            if (historicActivityInstance.getEndTime() != null) {
                finishedActivityInstanceList.add(historicActivityInstance);
            }
        }

        FlowNode currentFlowNode;
        FlowNode targetFlowNode;
        HistoricActivityInstance currentActivityInstance;
        // 遍历已完成的活动实例，从每个实例的outgoingFlows中找到已执行的
        for (int k = 0; k < finishedActivityInstanceList.size(); k++) {
            currentActivityInstance = finishedActivityInstanceList.get(k);
            // 获得当前活动对应的节点信息及outgoingFlows信息
            currentFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(currentActivityInstance
                    .getActivityId(), true);
            // 当前节点的所有流出线
            final List<SequenceFlow> outgoingFlowList = currentFlowNode.getOutgoingFlows();

            if ("parallelGateway".equals(currentActivityInstance.getActivityType()) || "inclusiveGateway".equals(
                    currentActivityInstance.getActivityType())) {
                // 遍历历史活动节点，找到匹配流程目标节点的
                for (final SequenceFlow outgoingFlow : outgoingFlowList) {
                    // 获取当前节点流程线对应的下级节点
                    targetFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(outgoingFlow.getTargetRef(),
                            true);
                    // 如果下级节点包含在所有历史节点中，则将当前节点的流出线高亮显示
                    if (allHistoricActivityNodeList.contains(targetFlowNode)) {
                        highLightedFlowIdList.add(outgoingFlow.getId());
                    }
                }
            } else {
                // 当前节点ID
                final String currentActivityId = currentActivityInstance.getActivityId();
                boolean ifStartFind = false;
                boolean ifFinded = false;
                HistoricActivityInstance historicActivityInstance;
                // 循环当前节点的所有流出线
                for (int i = 0; i < historicActivityInstanceList.size(); i++) {
                    // 历史节点
                    historicActivityInstance = historicActivityInstanceList.get(i);
                    //log.info("第【{}/{}】个历史节点-ActivityId=[{}]", i + 1, size, historicActivityInstance.getActivityId());
                    // 如果循环历史节点中的id等于当前节点id，从当前历史节点继续先后查找是否有当前节点流程线等于的节点
                    // 历史节点的序号需要大于等于已完成历史节点的序号，防止驳回重审一个节点经过两次是只取第一次的流出线高亮显示，第二次的不显示
                    if ((i >= k) && historicActivityInstance.getActivityId().equals(currentActivityId)) {
                        //log.info("第[{}]个历史节点和当前节点一致-ActivityId=[{}]", i + 1, historicActivityInstance.getActivityId());
                        ifStartFind = true;
                        // 跳过当前节点继续查找下一个节点
                        continue;
                    }
                    if (ifStartFind) {
                        //log.info("[开始]-循环当前节点-ActivityId=【{}】的所有流出线", currentActivityId);

                        ifFinded = false;
                        for (final SequenceFlow sequenceFlow : outgoingFlowList) {
                            // 如果当前节点流程线对应的下级节点在其后面的历史节点中，则该条流程线进行高亮显示
                            // 【问题】
                            //log.info("当前流出线的下级节点=[{}]", sequenceFlow.getTargetRef());
                            if (historicActivityInstance.getActivityId().equals(sequenceFlow.getTargetRef())) {
                                //log.info("当前节点[{}]需高亮显示的流出线=[{}]", currentActivityId, sequenceFlow.getId());
                                highLightedFlowIdList.add(sequenceFlow.getId());
                                // 暂时默认找到离当前节点最近的下一级节点即退出循环，否则有多条流出线时将全部被高亮显示
                                ifFinded = true;
                                break;
                            }
                        }
                    }
                    if (ifFinded) {
                        break;
                    }
                }
            }

        }
        return highLightedFlowIdList;
    }

}
